#ifndef __LOGGER_H
#define __LOGGER_H

#ifndef CONFIG_DEBUG_LEVEL
#define CONFIG_DEBUG_LEVEL 3
#endif

#ifndef CONFIG_DEBUG_COLOR
#define CONFIG_DEBUG_COLOR 1
#endif

#ifndef CONFIG_DEBUG_PREFIX
#define CONFIG_DEBUG_PREFIX 1
#endif

#ifdef CONFIG_DEBUG_COLOR
#define CONFIG_DEBUG_COLOR_RED "\x1b[31m"
#define CONFIG_DEBUG_COLOR_GREEN "\x1b[32m"
#define CONFIG_DEBUG_COLOR_YELLOW "\x1b[33m"
#define CONFIG_DEBUG_COLOR_BLUE "\x1b[34m"
#define CONFIG_DEBUG_COLOR_MAGENTA "\x1b[35m"
#define CONFIG_DEBUG_COLOR_DEFAULT "\x1b[0m"
#else
#define CONFIG_DEBUG_COLOR_RED
#define CONFIG_DEBUG_COLOR_GREEN
#define CONFIG_DEBUG_COLOR_YELLOW
#define CONFIG_DEBUG_COLOR_BLUE
#define CONFIG_DEBUG_COLOR_MAGENTA
#define CONFIG_DEBUG_COLOR_DEFAULT
#endif

#ifdef ONIX
#include <onix/syscall.h>
static unsigned int get_milliseconds_since_boot() {
   return time() % 10000000ULL;
}
#else
#if defined(_WIN32) || defined(_WIN64)  || defined(__MING32__)  || defined(__MINGW64__) || defined(__CYGWIN__)
#include <windows.h>
#include <stdint.h>
static inline uint32_t get_milliseconds_since_boot() {
    return GetTickCount64() % 10000000ULL;
}

#elif defined(__linux__)
#include <time.h>
#include <stdint.h>
static uint32_t get_milliseconds_since_boot() {
    struct timespec ts;
    clock_gettime(CLOCK_BOOTTIME, &ts);
    return ((uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000)  % 10000000ULL;
}

#elif defined(__APPLE__)
#include <mach/mach_time.h>
#include <stdint.h>
static uint32_t get_milliseconds_since_boot() {
    static mach_timebase_info_data_t info;
    if (info.denom == 0) {
        mach_timebase_info(&info);
    }
    uint64_t now = mach_absolute_time();
    return (now * info.numer / info.denom / 1000000)  % 10000000ULL;
}

#else
static unsigned long get_milliseconds_since_boot() {
   return 0;
}
#endif
#endif

extern int printf(const char *format, ...);


#ifdef CONFIG_DEBUG_PREFIX
#define log_print(COLOR, fmt, ...) printf(COLOR "[%07u] %s +%d %s: " fmt CONFIG_DEBUG_COLOR_DEFAULT, \
                                       get_milliseconds_since_boot(), __FILE__, __LINE__, __func__, \
                                       ##__VA_ARGS__)
#else
#define log_print(COLOR, fmt, ...) printf(fmt, ##__VA_ARGS__)
#endif

#if CONFIG_DEBUG_LEVEL > 3
#define dlog(fmt, args...)  log_print(CONFIG_DEBUG_COLOR_GREEN, fmt, ##args )
#else
#define dlog(fmt, args...)
#endif

#if CONFIG_DEBUG_LEVEL > 2
#define ilog(fmt, args...)  log_print(CONFIG_DEBUG_COLOR_DEFAULT, fmt, ##args )
#else
#define ilog(fmt, args...)
#endif

#if CONFIG_DEBUG_LEVEL > 1
#define wlog(fmt, args...)  log_print(CONFIG_DEBUG_COLOR_YELLOW, fmt, ##args )
#else
#define wlog(fmt, args...)
#endif

#if CONFIG_DEBUG_LEVEL > 0
#define elog(fmt, args...)  log_print(CONFIG_DEBUG_COLOR_RED, fmt, ##args )
#else
#define elog(fmt, args...)
#endif


#endif // logger.h